iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
Software Development

Haskell 從入門到放棄系列 第 10

[Haskell 從入門到放棄] Day 10 - 再談 higher order function

  • 分享至 

  • xImage
  •  

Filter

filter 是傳入一個會回傳 Bool 的 function 及 List,然後將 List 中每個元素丟進去 function 最後回傳所有執行該 function 後為 True 的元素。

:t filter --filter :: (a -> Bool) -> [a] -> [a]

filter (>8) [1..10] -- [9,10]
filter (`elem` ['a'..'c']) ['a'..'e'] -- "abc"

其實使用起來跟 map 有八成像,都是傳入 function 及 List。

稍微敏銳的讀者應該會發現其實上面的行為我用 List comprehension 也是能夠做到一樣的事情的

其實 map 也是能用 List comprehension 做到一樣的事哦

[x| x <- [1..10] , x >8 ]
[x| x <- ['a'..'e'] , x `elem` ['a'..'c']]

那至於什麼時候要用 List comprehension 什麼時候要用 filter 或者 map ,我覺得就看個人喜好以及用哪種方式寫起來比較順手了,在多重限制條件下可能用 List comprehension 會比 filtermap 較為易讀吧。

說回 filtermap ,他們應該也是 FP 中最常用到的function 了通常我們會同時用 mapfilter 的各種組合技來將我們想要的資料給變出來。

像是

  1. 取得 List 中所有偶數的平方
  2. 取得 List 中所有正數的平方根
squareEven :: [Int] -> [Int]
squareEven xs = 
    map (^2) (filter even xs)

squareRootOfPositives :: [Double] -> [Double]
squareRootOfPositives xs =
    map sqrt (filter (> 0) xs)

squareEven 是先將偶數取出來後再經過 map 讓每個數都取平方

squareRootOfPositives 則是講將大於 0 的數值取出來後再開根號

大多數時候我們

Lamda

lamda 就是匿名函數,最常用在 higher order function 上,有時候要傳入的 function 邏輯可能非常複雜,但又不想為此額外宣告一個 function 那我們就會用 lamda 來幫助我們。

使用上只要加一個 \ 就好了。

filter (\ x -> x `mod` 3 == 0 ||  x `mod` 7 == 0) [1..30]
-- [3,6,7,9,12,14,15,18,21,24,27,28,30]

這邊 (\ x -> ...)x 就是從 List 丟進去 lamda 的元素。

既然 lamda 像是一種 function 那我們當然可以繼續應用之前所說的特性像是 pattern matching,只是無法設置多個條件,所以其實是有機會發生 runtime error

map (\(x:xs) -> 2*x + sum xs) [[1..5],[5..10],[11,15]] -- [16,50,37]

我們可以藉此匹配到二維 List 中每個 List 的 第一個元素及剩下的元素並將第一個元素乘2後與剩下元素的加總相加。

也因為 curried function 的關係其實以下這兩種寫法是等價的

add:: Num a => a -> a -> a
add x y = x + y

add' :: Num a => a -> a -> a
add' = \x -> \y -> x + y

add' 剛好也很適合解釋 Num a => a -> a -> a 這個 type ,將第一次傳入的參數放進第一個 lamda 然後將第二次傳入的參數放進第二個 lamda


寫到現在相信讀者能夠開始體會到 FP 的好玩之處,會發現我們大多數時候是在想「資料要變什麼樣」而不是「要怎麼讓資料變成那樣」。


今天的程式碼

https://github.com/toddLiao469469/30days-for-haskell


上一篇
[Haskell 從入門到放棄] Day 09 - 終於來到 higher order function
下一篇
[Haskell 從入門到放棄] Day 11 - 繼續談 higher order function
系列文
Haskell 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言